package com.tarzan.redis.config;

import com.fasterxml.jackson.annotation.JsonAutoDetect;
import com.fasterxml.jackson.annotation.PropertyAccessor;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.tarzan.common.core.utils.Parse;
import com.tarzan.common.core.utils.PropUtil;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Qualifier;
import org.springframework.cache.annotation.EnableCaching;
import org.springframework.context.annotation.Bean;
import org.springframework.context.annotation.Configuration;
import org.springframework.data.redis.connection.RedisConnectionFactory;
import org.springframework.data.redis.connection.RedisPassword;
import org.springframework.data.redis.connection.RedisStandaloneConfiguration;
import org.springframework.data.redis.connection.lettuce.LettuceConnectionFactory;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.data.redis.core.StringRedisTemplate;
import org.springframework.data.redis.serializer.StringRedisSerializer;

/**
 * @author liujinshan
 * @Package com.tarzan.redis.config
 * @ClassName: RedisConfig
 * @Description:
 * @Version 1.0.0
 * @date 2021/5/18 16:09
 */
@EnableCaching //开启缓存
@Configuration  //配置类
public class RedisConfig {


    private static final Logger logger = LoggerFactory.getLogger(RedisConfig.class);
    private static final String HOST_NAME_KEY = "spring.redis.hostName";
    private static final String PORT_KEY = "spring.redis.port";
    private static final String PASSWORD_KEY = "spring.redis.password";
    private static final String DB_SELECT_KEY = "spring.redis.database";

    @Bean(name = "lettuceConnectionFactory")
    LettuceConnectionFactory initLettuceConnectionFactory() {
        String hostName = PropUtil.getInstance().getConfig(HOST_NAME_KEY, PropUtil.PUBLIC_CONF_REDIS);
        int port = Parse.toInt(PropUtil.getInstance().getConfig(PORT_KEY, PropUtil.PUBLIC_CONF_REDIS));
        String password = PropUtil.getInstance().getConfig(PASSWORD_KEY, PropUtil.PUBLIC_CONF_REDIS);
        int database = Parse.toInt(PropUtil.getInstance().getConfig(DB_SELECT_KEY, PropUtil.PUBLIC_CONF_REDIS));
        RedisStandaloneConfiguration redisStandaloneConfiguration = new RedisStandaloneConfiguration();
        redisStandaloneConfiguration.setHostName(hostName);
        redisStandaloneConfiguration.setPort(port);
        redisStandaloneConfiguration.setPassword(RedisPassword.of(password));
        redisStandaloneConfiguration.setDatabase(database);
        LettuceConnectionFactory lettuceConnectionFactory = new LettuceConnectionFactory(redisStandaloneConfiguration);
        logger.info("LettuceConnectionFactory bean init success , redis host = {} , redis port ={}", lettuceConnectionFactory.getHostName(), lettuceConnectionFactory.getPort());
        return lettuceConnectionFactory;
    }

    @Bean(name = "redisTemplate")
    public RedisTemplate<String, String> stringRedisTemplate(@Qualifier("lettuceConnectionFactory") LettuceConnectionFactory lettuceConnectionFactory) {
        return new StringRedisTemplate(lettuceConnectionFactory);
    }

    @Bean
    @SuppressWarnings(value = { "unchecked", "rawtypes", "deprecation" })
    public RedisTemplate<Object, Object> redisTemplate(RedisConnectionFactory connectionFactory)
    {
        RedisTemplate<Object, Object> template = new RedisTemplate<>();
        template.setConnectionFactory(connectionFactory);

        FastJson2JsonRedisSerializer serializer = new FastJson2JsonRedisSerializer(Object.class);

        ObjectMapper mapper = new ObjectMapper();
        mapper.setVisibility(PropertyAccessor.ALL, JsonAutoDetect.Visibility.ANY);
        mapper.enableDefaultTyping(ObjectMapper.DefaultTyping.NON_FINAL);
        serializer.setObjectMapper(mapper);

        template.setValueSerializer(serializer);
        // 使用StringRedisSerializer来序列化和反序列化redis的key值
        template.setKeySerializer(new StringRedisSerializer());
        template.afterPropertiesSet();
        return template;
    }

}
